
Ext.data.QcodoProxy = function(controlId, waitIconId, config){
    Ext.data.QcodoProxy.superclass.constructor.call(this);
    Ext.apply(this, config);
    this.controlId = controlId;
    this.waitIconId = waitIconId;
};

Ext.extend(Ext.data.QcodoProxy, Ext.data.DataProxy, {

    timeout : 30000,
    
    load : function(params, reader, callback, scope, arg){
        if(this.fireEvent("beforeload", this, params) !== false){
            
            var trans = {
                id : this.controlId,
                cb : "qcpCallback"+this.controlId,
                params : params,
                arg : arg,
                callback : callback,
                scope : scope,
                reader : reader
            };
            var conn = this;
            
            window[trans.cb] = function(o){
                conn.handleResponse(o, trans);
            };
            
            if(this.autoAbort !== false){
                this.abort();
            }
            
            trans.timeoutId = this.handleFailure.defer(this.timeout, this, [trans]);
			
            qc.pA(document.getElementById('Qform__FormId').value,
            	this.controlId,
            	'QExtLoadEvent',
            	Ext.util.JSON.encode(Ext.apply(params, {cb: trans.cb})),
            	this.waitIconId);
            
            this.trans = trans;
        }else{
            callback.call(scope||this, null, arg, false);
        }
    },

    // private
    isLoading : function(){
        return this.trans ? true : false;  
    },

    /**
     * Abort the current server request.
     */
    abort : function(){
        if(this.isLoading()){
            this.destroyTrans(this.trans);
        }
    },
    
    // private
    destroyTrans : function(trans, isLoaded){
        clearTimeout(trans.timeoutId);
        if(isLoaded){
            window[trans.cb] = undefined;
            try{
                delete window[trans.cb];
            }catch(e){}
        }else{
            // if hasn't been loaded, wait for load to remove it to prevent script error
            window[trans.cb] = function(){
                window[trans.cb] = undefined;
                try{
                    delete window[trans.cb];
                }catch(e){}
            }; 
        }
    },
    
    // private
    handleResponse : function(o, trans){
        this.trans = false;
        this.destroyTrans(trans, true);
        var result;
        try {
			var json = eval("("+o+")");
        	if(!json)
            	throw {message: "JsonReader.read: Json object not found"};
        	
            result = trans.reader.readRecords(json);
        }catch(e){
            this.fireEvent("loadexception", this, o, trans.arg, e);
            trans.callback.call(trans.scope||window, null, trans.arg, false);
            return;
        }
        this.fireEvent("load", this, o, trans.arg);
        trans.callback.call(trans.scope||window, result, trans.arg, true);
    },
    
    // private
    handleFailure : function(trans){
        this.trans = false;
        this.destroyTrans(trans, false);
        this.fireEvent("loadexception", this, null, trans.arg);
        trans.callback.call(trans.scope||window, null, trans.arg, false);
    }
});


// Allows multiple editors per cell
Ext.grid.AdvEditorGrid = function(container, config){
    Ext.grid.AdvEditorGrid.superclass.constructor.call(this, container, config);
};

Ext.extend(Ext.grid.AdvEditorGrid, Ext.grid.EditorGrid, {

    onCellDblClick : function(g, row, col, e){
    	var a = e.getTarget().attributes;
    	var ed = a.ed;
    	var edField = a.edfield;
    	var edAlign = a.edalign;
        this.startEditing(row, col, ed ? eval(ed.nodeValue) : null, edField ? edField.nodeValue : null, edAlign ? edAlign.nodeValue : null);
    },

    onEditComplete : function(ed, value, startValue){
        this.editing = false;
        this.activeEditor = null;
        ed.un("specialkey", this.selModel.onEditorKey, this.selModel);
        ed.alignment = ed.formerAlignment;
        if(String(value) != String(startValue)){
            var r = ed.record;
            var e = {
                grid: this,
                record: r,
                field: ed.recordField,
                originalValue: startValue,
                value: value,
                row: ed.row,
                column: ed.col,
                cancel:false
            };
            if(this.fireEvent("validateedit", e) !== false && !e.cancel){
                r.set(ed.recordField, e.value);
                delete e.cancel;
                this.fireEvent("afteredit", e);
            }
        }
        this.view.focusCell(ed.row, ed.col);
    },

    /**
     * Starts editing the specified for the specified row/column
     * @param {Number} rowIndex
     * @param {Number} colIndex
     */
    startEditing : function(row, col, ed, field, alignment){
        this.stopEditing();
        if(this.colModel.isCellEditable(col, row)){
            this.view.focusCell(row, col);
            var r = this.dataSource.getAt(row);
            field = field || this.colModel.getDataIndex(col);
            var e = {
                grid: this,
                record: r,
                field: field,
                value: r.data[field],
                row: row,
                column: col,
                cancel:false
            };
            if(this.fireEvent("beforeedit", e) !== false && !e.cancel){
                this.editing = true; // flag for buffering of orphan key strokes
                (function(){ // complex but required for focus issues in safari, ie and opera
                    ed = ed || this.colModel.getCellEditor(col, row);
                    ed.row = row;
                    ed.col = col;
                    ed.recordField = field;
                    ed.record = r;
                    ed.formerAlignment = ed.alignment;
                    if(alignment)
                    	ed.alignment = alignment;
                    ed.on("complete", this.onEditComplete, this, {single: true});
                    ed.on("specialkey", this.selModel.onEditorKey, this.selModel);
                    this.activeEditor = ed;
                    var v = r.data[field];
                    ed.startEdit(this.view.getCell(row, col), v);
                }).defer(50, this);
            }
        }
    }
});